//	--------------------------------------------------------------------
//	Copyright(C) 2006,2007 Zhao Yukun. All rights reserved.
//	This file is a part of the Xeres system.
//	Xeres 2007
//	Contact : xeres.engine@gmail.com
//	$(reservedInfo)
//	$(reservedDeclaration)
//	--------------------------------------------------------------------
///	@file	<tls.h>
///	@path	~/xeres/src/lib/system/
///	@date	2007/12/08
///	@desc	Thread local storage management.

#pragma once

#include "xeres.h"

// STL
#include <vector>
#include <map>

#include "lib/system/lock.h"
#include "lib/system/thread.h"
#include "lib/utilities/callback.h"
#include "lib/utilities/dir_tree.h"

namespace xeres {

	// TLS manage stage
	enum TLS_MANAGE
	{
		TLS_MANAGE_ALLOC_LOCAL = 0 ,
		TLS_MANAGE_FREE_LOCAL ,
		TLS_MANAGE_FREE_AT_EXIT ,
		TLS_MANAGE_last
	};

	/*!
		\class	Tls
		\brief	Thread local storage.
	*/
	class Tls
	{
	public:

		/// \instance
		static Tls& instance( void );

		/// \name Allocate & Acquire TLS
		//@{
	
		/*!
			\brief		Allocate TLS space & return index.
		*/
		int Alloc( size_t size , function<void(void*,TLS_MANAGE)> manage_call );

		/*!
			\brief		Acquire TLS of current thread (create while no space allocated).
		*/
		void * Acquire( int index );

		//@}

	private:

		/// \ctor
		Tls( void );

		/// \dtor
		virtual ~Tls( void );

		// friend
		friend class Thread;

		// call by thread while exit thread
		void OnThreadExit( void );

		// TLS size & handler
		struct _TlsSlot
		{
			size_t								m_size;
			function<void(void*,TLS_MANAGE)>	m_handler;
		};

		// allocate space for current thread by record
		void * AllocSpace( _TlsSlot& slot );

		// allocated space for current thread
		struct _TlsSpace
		{
			_TlsSlot *				m_slot;
			void *					m_space;
		};

		// current thread info
		struct _TlsThreadInfo
		{
			Thread *				m_thread; // NULL to indicate user-created thread
			std::vector<_TlsSpace>	m_spaces;
		};

		// cleanup thread
		void CleanupThread( _TlsThreadInfo * info );

		// data

		// op lock
		ThreadLock					m_lock;

		// record
		std::vector<_TlsSlot>		m_slots;

		// thread map
		typedef std::map<uint32,_TlsThreadInfo*> ThreadMap;
		ThreadMap					m_threadInfo;
	};

} // namespace xeres
